﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using MobySharp.Results;

namespace MobySharp.Actions
{
    public class SearchPosts : BaseAction, IAction
    {
        /// <summary>
        /// Throws NotImplementedException
        /// Initializes a new instance of the <see cref="SearchPosts"/> class.
        /// </summary>
        /// <remarks>Throws a NotImplementedException because action is not implemented</remarks>
        public SearchPosts()
        {
            Tags = new List<string>();

            RequestType = HTTPRequestType.Get;
            Action = APICall.searchPosts;
        }


        /// <summary>
        /// Amount of posts to show on each page
        /// </summary>
        /// <value>The items per page.</value>
        [PostDataInstruction("searchItemsPerPage", false)]
        public int ItemsPerPage { get; set; }

        /// <summary>
        /// The current page
        /// </summary>
        /// <value>The page.</value>
        [PostDataInstruction("searchPage", false)]
        public int Page { get; set; }

        /// <summary>
        /// Specifies for which words to search.
        /// </summary>
        /// <value>'mouse -animal'</value>
        [PostDataInstruction("searchTerms", false)]
        public string Terms { get; set; }

        /// <summary>
        /// Specifies in which mode to match the query string.
        /// </summary>
        /// <value>'all', 'any' or 'boolean'</value>
        [PostDataInstruction("searchTermsMode", false)]
        public string TermsMode { get; set; }

        /// <summary>
        /// Only return postings from the specified username
        /// </summary>
        /// <value>The username.</value>
        [PostDataInstruction("searchUsername", false)]
        public string Username { get; set; }

        /// <summary>
        /// Include photo posts in the search (default is Yes)
        /// </summary>
        /// <value>The search photo.</value>
        [PostDataInstruction("searchMediaPhoto", false)]
        public YesNo SearchPhoto { get; set; }

        /// <summary>
        /// Include video posts in the search (default is Yes)
        /// </summary>
        /// <value>The search video.</value>
        [PostDataInstruction("searchMediaVideo", false)]
        public YesNo SearchVideo { get; set; }

        /// <summary>
        /// Include audio posts in the search (default is Yes)
        /// </summary>
        /// <value>The search audio.</value>
        [PostDataInstruction("searchMediaAudio", false)]
        public YesNo SearchAudio { get; set; }

        /// <summary>
        /// Only return postings from the specified country (ISO3166 code2)
        /// </summary>
        /// <value>NL</value>
        [PostDataInstruction("searchGeoCountry", false)]
        public string GeoCountry { get; set; }

        /// <summary>
        /// Only return postings from the specified location (also see <seealso cref="GeoDistance"/>)
        /// </summary>
        /// <value>52.364752,4.902418</value>
        [PostDataInstruction("searchGeoLocation", false)]
        public PostMedia.LatLong GeoLocation { get; set; }

        /// <summary>
        /// Only return postings withing a range of 5000 meters from the specified <seealso cref="GeoLocation"/>
        /// </summary>
        /// <value>The geo distance.</value>
        [PostDataInstruction("searchGeoDistance", false)]
        public int GeoDistance { get; set; }

        /// <summary>
        /// Look for one or more tags
        /// </summary>
        [PostDataInstruction("searchTags", false)]
        public List<string> Tags { get; set; }

        /// <summary>
        /// Match all given tags, or any of them.
        /// </summary>
        /// <value>all of any</value>
        [PostDataInstruction("searchTagsMode", false)]
        public string TagsMode { get; set; }

        /// <summary>
        /// Sort the results based on this field.
        /// </summary>
        /// <value>'relevance', 'date', 'views' or 'geo'. Geo only if GPS location for <seealso cref="GeoDistance"/> is set properly</value>
        [PostDataInstruction("searchSortBy", false)]
        public string SortBy { get; set; }

        /// <summary>
        /// Specifies in which direction sorting should be done.
        /// </summary>
        /// <value>'asc' or 'desc'</value>
        [PostDataInstruction("searchOrder", false)]
        public string Order { get; set; }

        #region IAction Members

        public IResult ParseResult(string result)
        {
            var r = new SearchResult();
            try
            {
                if (result.Contains("<?xml"))
                {
                    var serializer = new XmlSerializer(r.GetType());
                    r = (SearchResult) serializer.Deserialize(new StringReader(result));

                    return r;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return r;
        }

        #endregion
    }
}